package api

import (
	"gitee.com/liuxiaowei123/vblog-3/app/blog"
	"gitee.com/liuxiaowei123/vblog-3/app/token"
	"gitee.com/liuxiaowei123/vblog-3/app/user"
	"gitee.com/liuxiaowei123/vblog-3/middlewares"
	"gitee.com/liuxiaowei123/vblog-3/response"
	"github.com/gin-gonic/gin"
)

// 定义实现blog接口层的结构体
type BlogApiHandler struct {
	blogsvc blog.BlogService
}

// 定义结构体的扩展方法，实现HandlerFunc注册到路由中
func (b *BlogApiHandler) Registry(r gin.IRouter) {
	v := r.Group("v1").Group("blogs")
	// http://localhost:8899/api/vblog3/v1/blogs
	v.GET("/", b.QueryBlog)
	// url路径里面有变量:id, 声明一个路径变量, 通过r.Params("id") 就可以获取到43
	v.GET("/:id", b.DescribeBlog)
	// 中间件认证; 表示下面的接口都需要认证
	v.Use(middlewares.NewTokenAuther().Auth)
	// v.POST("/", b.CreateBlog)
	v.POST("/", middlewares.Required(user.ROLE_AUDITOR), b.CreateBlog)
	v.PUT("/:id", b.UpdatePutBlog)
	v.PATCH("/:id", b.UpdatePatchBlog)
	// http://localhost:8899/api/vblog3/v1/blogs/74
	v.DELETE("/:id", b.DeleteBlog)
	// POST /api/vblog3/v1/blogs/43/audit
	// v1.POST("/:id/audit", b.AuditBlog)
}

// 定义结构体的扩展方法，实现路由中的HandlerFunc
// 通过c.BindJSON(&user) 将解析请求体中的 JSON 数据，并将其填充到 user 结构体中
func (b *BlogApiHandler) CreateBlog(c *gin.Context) {
	// 1、接收用户请求
	req := blog.NewCreateBlogRequest()
	err := c.BindJSON(req)
	if err != nil {
		response.Failed(c, err)
		return
	}
	// 1.1、从gin的上下文中，获取中间件认证过后的值,并补充内容
	ck := c.Keys[token.TOKEN_GIN_KEY_NAME]
	// 此处为什么要用指针类型断言呢（ck.(*token.Token)）？
	if ckcookie, ok := ck.(*token.Token); ok {
		req.CreateBy = ckcookie.UserName
	}
	// 2、处理请求
	bl, err := b.blogsvc.CreateBlog(c.Request.Context(), req)
	if err != nil {
		response.Failed(c, err)
	}
	// 3、返回响应
	response.Success(c, bl)
}

// 通过c.Query("key"): 获取查询字符串参数的值。，例如：/vblog/api/v1/blogs/?page_size=1&page_number=20
func (b *BlogApiHandler) QueryBlog(c *gin.Context) {
	// 1、获取用户请求
	req := blog.NewQueryBlogRequest()
	req.Keywords = c.Query("keywords")
	// 把string转换为int类型
	req.Usernames = c.QueryArray("Usernames")
	switch c.Query("status") {
	case "draft":
		// 错误代码，不能把常量直接转化为指针：req.Status = &blog.DRAFT_STATUS
		req.SetPoint(blog.DRAFT_STATUS)
	case "published":
		req.SetPoint(blog.PUBLISHED_STATUS)
	}
	req.ParsePageSize(c.Query("page_size"))
	req.ParsePageNumber(c.Query("page_number"))
	// 用下面代码做转换就会报错： "strconv.Atoi: parsing \"\": invalid syntax"
	// i, err := strconv.Atoi(c.Query("page_size"))
	// if err != nil {
	// 	response.Failed(c, err)
	// 	return
	// }
	// req.PageSize = i
	// i1, err := strconv.Atoi(c.Query("page_number"))
	// if err != nil {
	// 	response.Failed(c, err)
	// }
	// req.PageNumber = i1

	// 2、处理用户请求
	bl, err := b.blogsvc.QueryBlog(c.Request.Context(), req)
	if err != nil {
		response.Failed(c, err)
		return
	}
	// 3、返回响应
	response.Success(c, bl)
}

// 通过c.Param("key"): 获取URL路径参数的值，例如：/vblog/api/v1/blogs/43
func (b *BlogApiHandler) DescribeBlog(c *gin.Context) {
	// 1、获取用户请求
	req := blog.NewDescribeBlogRequest()
	// 错误代码: req.BlogId = c.Param("blog_id")
	req.BlogId = c.Param("id")
	// 2、处理用户请求
	bl, err := b.blogsvc.DescribeBlog(c.Request.Context(), req)
	if err != nil {
		response.Failed(c, err)
	}
	// 3、返回响应
	response.Success(c, bl)
}

// 更新时，要先查询，所以要c.Param
func (b *BlogApiHandler) UpdatePutBlog(c *gin.Context) {
	// 1、获取用户请求
	req := blog.NewUpdateBlogRequest(blog.NewCreateBlogRequest())
	req.BlogId = c.Param("id")
	req.UpdateMode = blog.UPDAET_PUT
	err := c.BindJSON(req)
	if err != nil {
		response.Failed(c, err)
	}
	// 2、处理用户请求
	bl, err := b.blogsvc.UpdateBlog(c.Request.Context(), req)
	if err != nil {
		response.Failed(c, err)
	}
	// 3、返回响应
	response.Success(c, bl)
}

func (b *BlogApiHandler) UpdatePatchBlog(c *gin.Context) {
	// 1、获取用户请求
	req := blog.NewUpdateBlogRequest(blog.NewCreateBlogRequest())
	req.BlogId = c.Param("id")
	req.UpdateMode = blog.UPDATE_PATCH
	err := c.BindJSON(req)
	if err != nil {
		response.Failed(c, err)
	}
	// 2、处理用户请求
	bl, err := b.blogsvc.UpdateBlog(c.Request.Context(), req)
	if err != nil {
		response.Failed(c, err)
	}
	// 3、返回响应
	response.Success(c, bl)
}

func (b *BlogApiHandler) DeleteBlog(c *gin.Context) {
	// 1、获取用户请求
	req := blog.NewDeleteBlogRequest()
	req.BlogId = c.Param("id")
	// 2、处理用户请求
	err := b.blogsvc.DeleteBlog(c.Request.Context(), req)
	if err != nil {
		response.Failed(c, err)
	}
	// 3、返回响应
	response.Success(c, "OK")
}
